package main

import (
	"fmt"
	"gocv.io/x/gocv"
	"image"
	_ "image"
	"image/color"
	_ "image/png"
	"math"
)

func main() {
	getCorrect("main/777.jpg")
}
func getCorrect(fileurl string){
	//read
	graycycle:=gocv.IMRead(fileurl,gocv.IMReadColor)
	if graycycle.Empty(){
		fmt.Println("读取图片失败")
	}
	//Warning:Garbled
	window:= gocv.NewWindow("原始图")
	window.IMShow(graycycle)
	window.WaitKey(1000)
	//get Spin angle
	angle:=CalcDegree(graycycle)
	dst := gocv.NewMat()
	//Change Original image
	rotateImg(graycycle,&dst,angle)
}


func CalcDegree(src gocv.Mat,) float64{
	var best_angle float64
	var max_cnt int
	total:=make(map[float64]int)
	//var midImage,dstImage gocv.Mat   ||Error：notwork
	midImage := gocv.NewMat()
	dstImage := gocv.NewMat()
	//Canny finds edges in an image using the Canny algorithm.
	//The smallest value between threshold1 and threshold2 is used for edge linking
	gocv.Canny(src,&midImage,50,200)
	//It converts the src Mat image to the dst Mat using the
	//code param containing the desired ColorConversionCode color space.
	gocv.CvtColor(midImage,&dstImage,gocv.ColorGrayToBGR)
	lines:=gocv.NewMat()
	//HoughLinesP implements the probabilistic Hough transform
	//algorithm for line detection(Hough变换检测直线，threshold为阈值，越高干扰愈低)
	gocv.HoughLinesPWithParams(midImage,&lines,1,math.Pi/180,290,80,200)
	for i := 0; i < lines.Rows(); i++ {
		//x,y Point in Image,Two Point can defined a straight line
		pt1 := image.Pt(int(lines.GetVeciAt(i, 0)[0]), int(lines.GetVeciAt(i, 0)[1]))
		pt2 := image.Pt(int(lines.GetVeciAt(i, 0)[2]), int(lines.GetVeciAt(i, 0)[3]))
		//draw Line in Image(color)
		gocv.Line(&dstImage, pt1, pt2, color.RGBA{0, 255, 0, 50}, 10)
		//angle=arctan(y/x)
		ang_:=math.Atan2(float64(lines.GetVeciAt(i, 0)[3])-float64(lines.GetVeciAt(i, 0)[1]),float64(lines.GetVeciAt(i, 0)[2])-float64(lines.GetVeciAt(i, 0)[0]))
		//transfer radian(弧度) to angle
		theta:=math.Pi/2 + ang_
		fingle:=theta/math.Pi*360
		fingle=math.Round(180-fingle)
		//???
		fingle=-1*fingle/2
		//Use HashMap storage most data
		_,ok:=total[fingle]
		if ok{
			total[fingle]++
			if total[fingle]>max_cnt {
				max_cnt = total[fingle]
				best_angle = fingle
			}
		}else{
			total[fingle] = 1
		}
	}
	window := gocv.NewWindow("直线图")
	window.ResizeWindow(800,400)
	window.IMShow(dstImage)
	window.WaitKey(1000)
	fmt.Println("图像将绕逆时针旋转：",best_angle)
	return best_angle
}


func rotateImg(src gocv.Mat,dst *gocv.Mat,angle float64){
	length:=math.Sqrt(float64(src.Rows()*src.Rows()+src.Cols()+src.Cols()))

	//pt3:=image.Point{X: (src.Rows()-350)/2,Y: (src.Cols()-250)/2}
	pt3:=image.Point{X: (src.Rows()-350)/2,Y: (src.Cols()-250)/2}
	sz:=image.Point{X: int(length*1.6),Y: int(length)}
	//sz:=image.Point{X: int(length),Y: int(length)}

	M:=gocv.GetRotationMatrix2D(pt3,angle,1)
	//gocv.WarpAffineWithParams(src,dst,M,sz,gocv.InterpolationLinear,gocv.BorderWrap,color.RGBA{R: 0,G: 0,B: 0,A: 1})
	gocv.WarpAffine(src,dst,M,sz)
	window := gocv.NewWindow("最终图")
	window.ResizeWindow(800,400)
	window.IMShow(*dst)
	window.WaitKey(10000)
}